export namespace BBM {
    export class BBM {
        constructor() {
            this.bbmInfo = new BBM_info();
            this.bbmTables = new BBM_tableCollection();
            this.bbmExtend = new Map<String, any>();
        }
        public bbmInfo: BBM_info;
        public bbmTables: BBM_tableCollection;
        public bbmExtend: Map<String, any>;

        addTable(table: BBM_table): void {
            const index = this.bbmTables.findIndex(t => t.name === table.name);
            if (index == -1) {
                // this.BBM_tables.unshift(table);
                this.bbmTables.push(table);
            }
        }
        getTable(tableName: string): BBM_table | undefined {
            return this.bbmTables.find(t => t.name === tableName)
        }

        removeTable(tableName: string) {
            const i = this.bbmTables.findIndex(t => t.name == tableName);
            if (i != -1) {
                this.bbmTables.splice(i, 1);
            }
        }
    }

    class BBM_info {
        constructor() { }
        public code: number = 0;
        public sender: string = '';
        public ip: string = '';
        public message: string = '';
        public bbm: string = 'BBM';

        // get _code(): number {
        //     return this.code;
        // }

    }

    export class BBM_column {
        constructor(name: string, caption?: string, dataType?: string) {
            this.name = name;
            this.caption = caption || 'defaultCaption';
            this.dataType = dataType || 'S';
        }
        public name: string;
        public caption: string;
        public dataType: string;
    }

    class BBM_columnCollection extends Array<BBM_column>{
        constructor() {
            super()
        }
    }

    export class BBM_row extends Array<any>{
        constructor() {
            super()
        }
    }

    class BBM_rowCollection extends Array<BBM_row> {
        constructor() {
            super()
        }
    }

    export class BBM_table {
        constructor() { }
        public name: string = 'BBM_TABLE_DEFAULT';
        public cols: BBM_columnCollection = [];
        public rows: BBM_rowCollection = [];
        public tableExtend: Map<string, any> = new Map();

        /**
         * 增加列
         * @param column 
         * @param caption 
         * @param dataType 
         */
        addColumn(column: BBM_column | string, caption?: string, dataType?: string): void {
            if (column instanceof BBM_column) {
                let index = this.cols.findIndex(e => {
                    e.name === column.name
                });
                if (index == -1) {
                    this.cols.push(column);
                    // 有数据的时候新增列 行push一个值
                    this.rows.forEach(r => r.push(''));
                    return;
                } else {
                    throw new Error(column + " column already exists");
                }
            } else {
                const a = new BBM_column(column, caption, dataType);
                this.addColumn(a);
            }
        }

        addColumns(cols1: string, ...columns: string[]): void {
            const c = [cols1, ...columns]
            c.forEach(e => {
                this.addColumn(e);
            })
        }

        removeColumn(column: string): void {
            const a = this.cols.findIndex(e => e.name === column);
            if (a != -1) {
                // 删除列的时候要对应删除行的值
                this.cols.splice(a, 1);
                this.rows.forEach(element => {
                    element.splice(a, 1);
                });
            }
        }

        addRow(row1: BBM_row | any, ...rows: any[]): void {
            if (row1 instanceof BBM_row) {
                if (row1.length != this.cols.length) {
                    throw new Error("The size of the new row must be equal to the size of the column");
                } else {
                    this.rows.push(row1);
                    return;
                }
            } else {
                const a = [row1, ...rows];
                const b = new BBM_row();
                a.forEach(e => {
                    b.push(e);
                })
                this.addRow(b)
            }
        }

        /**
         * 获取第一行
         * @returns 第一行的map对象
         */
        getFirstRow(): Map<string, any> | undefined {
            let m = new Map<string, any>();
            if (this.rows.length == 0) {
                return;
            }
            for (let i = 0; i < this.cols.length; i++) {
                const e = this.cols[i];
                m.set(e.name, this.rows[0][i]);
            }
            return m;
        }

        /**
         * 获取某一行
         * @param index 行号
         * @returns 行的map对象
         */
        getRow(index: number): Map<string, any> | undefined {
            let m = new Map<string, any>();
            if (this.rows.length < index) {
                return;
            }
            for (let i = 0; i < this.cols.length; i++) {
                const e = this.cols[i];
                m.set(e.name, this.rows[index][i]);
            }
            return m;
        }

        /**
         * 得到单元格的值
         * @param index 行号
         * @param colName 列名称
         * @returns object
         */
        getRowValue(index: number, colName: string): any {
            if (this.rows.length <= 0) return;
            const i = this.cols.findIndex(c => c.name === colName);
            if (i == -1) return;
            return this.rows[index][i]
        }

        /**
         * 修改单元格的值
         * @param index 行号
         * @param colName 列名
         * @param value 要修改的值
         */
        setRowValue(index: number, colName: string, value: any): void {
            if (this.rows.length <= 0 || index < 0) {
                throw new Error("this rows length maybe < 0 ||index < 0 ");
            }
            const i = this.cols.findIndex(c => c.name === colName);
            if (i == -1) {
                throw new Error(colName + "col not found");
            }
            this.rows[index].splice(i, 1, value);
            // this.rows[index][i] = value;
        }

        clone(): BBM_table {
            // 克隆table的表结构 不包括数据
            let obj = JSON.parse(JSON.stringify(this)) as BBM_table;
            obj.rows.length = 0;
            return obj;
        }
    }

    class BBM_tableCollection extends Array<BBM_table> {
        constructor() {
            super()
        }
    }
}